using System;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.SceneManagement;

[System.Serializable]
public class RoomTypePrefabs
{
    public int roomType; // 房间类型
    public List<GameObject> prefabs; // 对应的预制体列表
}


[System.Serializable]
public class SP_RoomPrefabs
{
    public string sceneName; // 场景名称
    
    public GameObject prefabUp; // 向上的预制体
    public GameObject prefabDown; // 向下的预制体
    public GameObject prefabLeft; // 向左的预制体
    public GameObject prefabRight; // 向右的预制体
}


public class DungeonGenerator : MonoBehaviour
{
    public GameObject PathFinder;
    private int times = 0; //递归次数
    private string currentScene; //获得当前scene名//其他不能用 只用于ini

    public Vector3 initialRoomPosition; // 用于存储初始房间的位置
    List<(int, int)> singlerooms = new List<(int, int)>(); //用来存单独房间

    [SerializeField] private int size = 10; // 地牢的大小
    [SerializeField] private int roomCount = 17; // 房间的数量
    
    // 各个场景的预制体列表（使用嵌套结构）
    [SerializeField] private List<RoomTypePrefabs> roomPrefabsScene1;
    [SerializeField] private List<RoomTypePrefabs> roomPrefabsScene2;
    [SerializeField] private List<RoomTypePrefabs> roomPrefabsScene3;

    // 初始房间预制体列表
    [SerializeField] private List<GameObject> initialRoomPrefabsList; //元素0-》scene1 以此类推

    // 特殊房间预制体列表
    [SerializeField] private List<SP_RoomPrefabs> bossRoomPrefabsList;
    [SerializeField] private List<SP_RoomPrefabs> dreamRoomPrefabsList;
    [SerializeField] private List<SP_RoomPrefabs> shopRoomPrefabsList;
    [SerializeField] private List<SP_RoomPrefabs> rewardRoomPrefabsList;

    private Dictionary<int, List<GameObject>> roomTypePrefabs;
    private static System.Random random = new System.Random(); // 随机数生成器
    private const float xOffset = 20f; // X方向上的偏移量
    private const float yOffset = 20f; // Y方向上的偏移量
    private GameObject Player;

    void Start()
    {
        currentScene = SceneManager.GetActiveScene().name;
        Debug.Log("_+_+_+_+_+_+:"+currentScene);
        Player = GameObject.Find("Player");

        // 初始化字典，根据当前场景加载相应的预制体
        roomTypePrefabs = new Dictionary<int, List<GameObject>>();
        InitializeRoomTypePrefabs();
        // 输出初始化后的预制体信息
        foreach (var kvp in roomTypePrefabs)
        {
           // Debug.Log($"房间类型 {kvp.Key} 有 {kvp.Value.Count} 个预制体。");
        }

        // 生成地牢网格
        int[,] dungeon = GenerateDungeonV5(size, roomCount);
        if (dungeon != null)
        {
            Debug.Log("房间网格:\n" + GridToString(dungeon)); // 打印网格数据
            // 实例化地牢
            InstantiateDungeon(dungeon);
            Debug.Log(TestDungeonWithSingleNeighbors(dungeon)); // 输出测试结果
        }
        else
        {
            Debug.Log("未能生成满足条件的地牢！");
        }

        //初始化玩家位置
        Player.transform.position = initialRoomPosition;
        //开启A*
        PathFinder.SetActive(true);
    }

    private void InitializeRoomTypePrefabs()
    {
        //string currentScene = SceneManager.GetActiveScene().name;
        List<RoomTypePrefabs> roomPrefabs = null;

        if (currentScene == "Scene1")
        {
            roomPrefabs = roomPrefabsScene1;

        }
        else if (currentScene == "Scene2")
        {
            roomPrefabs = roomPrefabsScene2;
        }
        else if (currentScene == "Scene3")
        {
            roomPrefabs = roomPrefabsScene3;
        }

        if (roomPrefabs == null) Debug.LogError("Sence roomPrefab没有挂载，检查房间生成器");


        foreach (var roomTypePrefab in roomPrefabs)
        {
            roomTypePrefabs[roomTypePrefab.roomType] = roomTypePrefab.prefabs;
        }
    }

    private int[,] InitializeGrid(int size)
    {
        int[,] grid = new int[size, size];
        for (int i = 0; i < size; i++)
        {
            for (int j = 0; j < size; j++)
            {
                grid[i, j] = -1;
            }
        }

        return grid;
    }

    private List<(int, int)> GetNeighbors(int x, int y, int size)
    {
        List<(int, int)> directions = new List<(int, int)> { (-1, 0), (1, 0), (0, -1), (0, 1) };
        List<(int, int)> neighbors = new List<(int, int)>();
        foreach (var direction in directions)
        {
            int nx = x + direction.Item1;
            int ny = y + direction.Item2;
            if (nx >= 0 && nx < size && ny >= 0 && ny < size)
            {
                neighbors.Add((nx, ny));
            }
        }

        return neighbors;
    }

    private void UpdateDirections(int[,] grid, int x, int y)
    {
        // 每个方向的位值定义
        Dictionary<(int, int), int> directionMap = new Dictionary<(int, int), int>
        {
            { (-1, 0), 1 }, // 上
            { (1, 0), 2 }, // 下
            { (0, -1), 4 }, // 左
            { (0, 1), 8 } // 右
        };

        int direction = 0;

        // 检查每个方向是否有房间连接
        foreach (var kvp in directionMap)
        {
            int nx = x + kvp.Key.Item1;
            int ny = y + kvp.Key.Item2;

            // 确保邻居房间在范围内且已存在
            if (nx >= 0 && nx < grid.GetLength(0) && ny >= 0 && ny < grid.GetLength(1) && grid[nx, ny] != -1)
            {
                direction |= kvp.Value; // 按位或运算更新方向编码
            }
        }

        grid[x, y] = direction;
    }

    private HashSet<(int, int)> Bfs(int[,] grid, (int, int) start)
    {
        Queue<(int, int)> queue = new Queue<(int, int)>();
        HashSet<(int, int)> visited = new HashSet<(int, int)>();

        queue.Enqueue(start);
        visited.Add(start);

        while (queue.Count > 0)
        {
            var (x, y) = queue.Dequeue();
            foreach (var neighbor in GetNeighbors(x, y, grid.GetLength(0)))
            {
                if (grid[neighbor.Item1, neighbor.Item2] != -1 && !visited.Contains(neighbor))
                {
                    visited.Add(neighbor);
                    queue.Enqueue(neighbor);
                }
            }
        }

        return visited;
    }

    private bool IsConnectedAndValid(int[,] grid)
    {
        List<(int, int)> rooms = new List<(int, int)>();
        for (int i = 0; i < grid.GetLength(0); i++)
        {
            for (int j = 0; j < grid.GetLength(1); j++)
            {
                if (grid[i, j] != -1)
                {
                    rooms.Add((i, j));
                }
            }
        }

        if (rooms.Count == 0)
        {
            return false;
        }

        var visited = Bfs(grid, rooms[0]);
        return visited.Count == rooms.Count;
    }

    private string TestDungeonWithSingleNeighbors(int[,] grid)
    {
        if (!IsConnectedAndValid(grid))
        {
            return "Grid is not valid or connected!";
        }

        for (int i = 0; i < grid.GetLength(0); i++)
        {
            for (int j = 0; j < grid.GetLength(1); j++)
            {
                if (grid[i, j] != -1)
                {
                    singlerooms.Add((i, j));
                }
            }
        }

        // 打印单独房间的坐标
        foreach (var room in singlerooms)
        {

            //Debug.Log($"单独房间坐标: ({room.Item1}, {room.Item2})   " );

        }

        int singleNeighborCount = 0;

        foreach (var room in singlerooms)
        {
            int neighbors = 0;
            foreach (var neighbor in GetNeighbors(room.Item1, room.Item2, grid.GetLength(0)))
            {
                if (grid[neighbor.Item1, neighbor.Item2] != -1)
                {
                    neighbors++;

                }
            }

            if (neighbors == 1)
            {
                singleNeighborCount++;
            }
        }

        return $"Grid has {singleNeighborCount} rooms with exactly one neighbor.";
    }

    private int[,] GenerateDungeonV5(int size, int roomCount, int maxAttempts = 1000)
    {
        random = new System.Random((int)DateTime.Now.Ticks);
        int attempts = 0;

        while (attempts < maxAttempts)
        {
            int[,] grid = InitializeGrid(size);
            int placedRooms = 0;
            Queue<(int, int)> queue = new Queue<(int, int)>();

            int start_x = random.Next(size);
            int start_y = random.Next(size);
            grid[start_x, start_y] = 0;
            queue.Enqueue((start_x, start_y));
            placedRooms++;

            while (queue.Count > 0 && placedRooms < roomCount)
            {
                var (x, y) = queue.Dequeue();
                var neighbors = GetNeighbors(x, y, size);
                Shuffle(neighbors);

                foreach (var neighbor in neighbors)
                {
                    if (grid[neighbor.Item1, neighbor.Item2] == -1 && placedRooms < roomCount)
                    {
                        if (random.NextDouble() < 0.5)
                        {
                            continue;
                        }

                        grid[neighbor.Item1, neighbor.Item2] = 0;
                        queue.Enqueue((neighbor.Item1, neighbor.Item2));
                        placedRooms++;
                    }
                }
            }

            if (placedRooms == roomCount && IsConnectedAndValid(grid))
            {
                for (int i = 0; i < size; i++)
                {
                    for (int j = 0; j < size; j++)
                    {
                        if (grid[i, j] != -1)
                        {
                            UpdateDirections(grid, i, j);
                        }
                    }
                }

                // string result = TestDungeonWithSingleNeighbors(grid);
                // int singleNeighborCount = int.Parse(result.Split(' ')[2]);
                // 调用单独的方法计算单邻居房间数
                int singleNeighborCount = CountSingleNeighbors(grid, size);
                
                //至少不少于4个单独房间（4个是特殊房间）
                if (singleNeighborCount >= 4)
                {
                    Debug.Log("单独房间个数"+ singleNeighborCount);
                    return grid;
                }
            }
            attempts++;
        }
        return null;
    }

    private int CountSingleNeighbors(int[,] grid, int size)
    {
        int count = 0; // 初始化单邻居房间计数
        for (int i = 0; i < size; i++)
        {
            for (int j = 0; j < size; j++)
            {
                if (grid[i, j] != -1) // 仅检查存在的房间
                {
                    int neighborCount = 0;
                    var neighbors = GetNeighbors(i, j, size); // 获取邻居列表

                    foreach (var (nx, ny) in neighbors)
                    {
                        if (grid[nx, ny] != -1) // 检查是否是房间
                        {
                            neighborCount++;
                        }
                    }

                    if (neighborCount == 1) // 如果仅有一个邻居
                    {
                        count++;
                    }
                }
            }
        }
        return count; // 返回单邻居房间的数量
    }

    private void Shuffle<T>(List<T> list)
    {
        int n = list.Count;
        while (n > 1)
        {
            n--;
            int k = random.Next(n + 1);
            T value = list[k];
            list[k] = list[n];
            list[n] = value;
        }
    }


    // 实例化地牢
    private void InstantiateDungeon(int[,] grid)
    {
        bool bossRoomGenerated = false; //boss房
        bool shopRoomGenerated = false; // 标记是否生成过商店房间
        bool rewardRoomGenerated = false; // 标记是否生成过奖励房间
        bool dreamRoomGenerated = false; //梦


        int size = grid.GetLength(0);
        bool initialRoomPlaced = false; //初始房间是否生成
        bool initialRoomFound = false;
        bool hasRoomType2 = false;     // 是否找到 roomType 为 2 的房间
        int startX = 0;
        int startY = 0;
        bool uesdStartroom = false;
        bool[,] isRoomInit = new bool[size, size];
        // 清空数组，将所有值设为 false
        Array.Clear(isRoomInit, 0, isRoomInit.Length);

        // 首先扫描地牢网格以确定是否同时存在 roomType 为 15 和 2的房间
        for (int i = 0; i < size; i++)
        {
            for (int j = 0; j < size; j++)
            {
                if (grid[i, j] == 15)
                {
                    initialRoomFound = true;
                    if (!uesdStartroom)
                    {
                        startX = i;
                        startY = j;
                    }
                }

                if (grid[i, j] == 2)
                {
                    hasRoomType2 = true; // 记录是否找到 roomType 为 2 的房间
                }

                // 如果两种房间类型都已找到，则跳出循环
                if (initialRoomFound && hasRoomType2)
                {
                    break;
                }
            }

            // 外层循环检查跳出条件
            if (initialRoomFound && hasRoomType2)
            {
                break;
            }
        }

        // 如果未找到 roomType 为 15 的房间，则重新生成地牢
        //可以增加roll地牢的条件
        if (!initialRoomFound || !hasRoomType2)
        {
            Debug.LogWarning("未找到 roomType 为 15 的房间，重新生成地牢...");
            int[,] newGrid = GenerateDungeonV5(size, roomCount);

            if (newGrid != null)
            {
                // Debug.Log("重新生成的地牢网格：\n" + GridToString(newGrid)); // 打印网格数据
                times++; //递归次数
                InstantiateDungeon(newGrid); // 递归调用，重新生成地牢
            }
            else
            {
                Debug.LogError("重新生成地牢大失败！");
            }

            return; // 退出当前方法，避免继续执行
        }

        //计算对应最远的boss房
   for (int i = 0; i < size; i++)
        {
            for (int j = 0; j < size; j++)
            {
                // if (isRoomInit[i, j])
                // {
                //     continue; //如果已经之前已经生成 那就跳过
                // }

                if (grid[i, j] > -1)
                {
                    int roomType = grid[i, j]; // 房间类型（连接方向值）
                    Vector3 position = new Vector3(j * yOffset, -i * xOffset, 0); // 根据偏移计算位置
                    
                    if (roomTypePrefabs.ContainsKey(roomType))
                    {
                        List<GameObject> prefabs = roomTypePrefabs[roomType];
                        if (prefabs == null || prefabs.Count == 0)
                        {
                            Debug.LogWarning($"房间类型 {roomType} 没有分配任何预制体。");
                            continue; // 跳过当前循环
                        }

                        GameObject roomPrefab = prefabs[random.Next(prefabs.Count)]; // 随机选择一个预制体
                        if (roomPrefab != null)
                        {
                            //判断场景以选择不同场景的初始房间prefab
                            if (roomType == 15 && !initialRoomPlaced && startX == i && startY == j) 
                            {

                                GameObject StartroomPrefab = null;
                                if (currentScene == "Scene1")
                                {
                                    StartroomPrefab = initialRoomPrefabsList[0];

                                }
                                else if (currentScene == "Scene2")
                                {
                                    StartroomPrefab = initialRoomPrefabsList[1];
                                }
                                else if (currentScene == "Scene3")
                                {
                                    StartroomPrefab = initialRoomPrefabsList[2];
                                }
                                else
                                {
                                    Debug.LogError("secne名不对导致初始房间生成失败 ，或者是scene名字没对应上，请检查");
                                }

                                if (StartroomPrefab == null)
                                {
                                    Debug.LogError("123scene的初始房间没挂载上");
                                }

                                // 实例化第一个 roomType 为 15 的房间作为初始房间
                                GameObject instantiatedRoom =
                                    Instantiate(StartroomPrefab, position, Quaternion.identity, transform);
                                instantiatedRoom.name = "InitialRoom"; // 设置实例化对象的名字
                                initialRoomPosition = position;
                                
                                initialRoomPlaced = true;
                                
                                Debug.Log($"初始房间（类型15）已在位置 {position} 实例化。");
                                continue;
                            }
                            
                            if (roomType == 1 || roomType == 2 || roomType == 8 || roomType == 4)
                            {
                                
                                if (!bossRoomGenerated && roomType == 2)
                                {

                                    GameObject bossRoomPrefab = GetRoomPrefab(bossRoomPrefabsList, currentScene, roomType);
                                    GameObject instantiatedRoom =
                                        Instantiate(bossRoomPrefab, position, Quaternion.identity, transform);
                                    instantiatedRoom.name = "bossRoom"; // 设置实例化对象的名字
                                    bossRoomGenerated = true;
                                    continue;
                                    
                                    
                                }

                                if (!shopRoomGenerated)
                                {
                                    
                                    GameObject ShopRoomPrefab = GetRoomPrefab(shopRoomPrefabsList, currentScene, roomType);
                                    GameObject instantiatedRoom =
                                        Instantiate(ShopRoomPrefab, position, Quaternion.identity, transform);
                                    instantiatedRoom.name = "ShopRoom"; // 设置实例化对象的名字
                                    
                                    shopRoomGenerated = true;
                                    
                                    continue;
                                }

                                if (!dreamRoomGenerated)
                                {
                                    GameObject DreamRoomPrefab = GetRoomPrefab(dreamRoomPrefabsList, currentScene, roomType);
                                    GameObject instantiatedRoom =
                                        Instantiate(DreamRoomPrefab, position, Quaternion.identity, transform);
                                    instantiatedRoom.name = "dreamRoom"; // 设置实例化对象的名字
                                    
                                    dreamRoomGenerated = true;
                                    continue;
                                }

                                if (!rewardRoomGenerated)
                                {
                                    GameObject rewardRoomPrefab = GetRoomPrefab(rewardRoomPrefabsList, currentScene, roomType);
                                    GameObject instantiatedRoom =
                                        Instantiate(rewardRoomPrefab, position, Quaternion.identity, transform);
                                    instantiatedRoom.name = "rewardRoom"; // 设置实例化对象的名字

                                    rewardRoomGenerated = true;
                                    continue;
                                }
                            }
                            
                            
                            Instantiate(roomPrefab, position, Quaternion.identity, transform);
                                //Debug.Log(
                                // $"实例化房间类型 {roomType} 的预制体 {roomPrefab.name} 在位置 ({position.x}, {position.y}, {position.z})。");
                            
                        }
                        else
                        {
                            Debug.LogError($"房间类型 {roomType} 的预制体为 null。");
                        }
                    }
                    else
                    {
                        Debug.LogWarning($"意外的房间类型：{roomType}");
                    }
                }
            }
        }

        if (!initialRoomPlaced) Debug.LogError("没有生成初始房间");
    }


    // 将二维数组格式化为字符串，方便调试输出
    private string GridToString(int[,] grid)
    {
        if (grid == null)
        {
            return "Grid is null!";
        }
    
        int rows = grid.GetLength(0);
        int cols = grid.GetLength(1);
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
    
        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < cols; j++)
            {
                int a = grid[i, j];
                sb.Append(a.ToString().PadLeft(3)); // 每个值占3个字符宽度，方便对齐
            }
    
            sb.AppendLine(); // 换行
        }
    
        return sb.ToString();
    }

    private float CalculateDistance(int x1, int y1, float x2, float y2) //算距离
    {
        return Mathf.Sqrt(Mathf.Pow(x2 - x1, 2) + Mathf.Pow(y2 - y1, 2));
    }

//    // 根据当前场景和方向选择房间预制体
    private GameObject GetRoomPrefab(List<SP_RoomPrefabs> roomPrefabsList, string currentScene, int walltype)
    {
        foreach (var roomPrefabs in roomPrefabsList)
        {
            if (roomPrefabs.sceneName == currentScene)
            {
                switch (walltype)
                {
                    case 1:
                        return roomPrefabs.prefabUp;
                    case 2:
                        return roomPrefabs.prefabDown;
                    case 4:
                        return roomPrefabs.prefabLeft;
                    case 8:
                        return roomPrefabs.prefabRight;
                }
            }
        }
        return null;
    }
//
//         Debug.LogError($"未找到适用于场景 {currentScene} 和 walltype {walltype} 的房间预制体。");
//         return null;
//     }
//
//         private void OnDrawGizmos() // 背景网格方法
//         {
//             if (!Application.isPlaying) return;
//         
//             int[,] grid1 = GenerateDungeonV5(size, roomCount);
//             if (grid1 == null) return;
//             
//             Gizmos.color = Color.red;
//             int rows = grid1.GetLength(0);
//             int cols = grid1.GetLength(1);
//         
//             for (int i = 0; i < rows; i++)
//             {
//                 for (int j = 0; j < cols; j++)
//                 {
//                     Vector3 position = new Vector3(i * xOffset, -j * yOffset, 0);
//                     string text = grid1[i, j] == -1 ? "XX" : grid1[i, j].ToString();
//                     UnityEditor.Handles.Label(position, text); // 在场景中显示
//                 }
//             }
//         }
//
//
//    
}
